﻿// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

using System.Windows;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace TheOliver.Controls
{

    /// <summary>
    /// Trigger for specific key events such as 'space key' or 'Control-A'.
    /// </summary>
    public sealed class KeyTrigger : TriggerBase<FrameworkElement>
    {

        private FrameworkElement root;

        /// <summary>
        /// The key press which this is to be triggered on.
        /// </summary>
        public Key Key
        {
            get { return (Key)GetValue(KeyProperty); }
            set { SetValue(KeyProperty, value); }
        }

        /// <summary>
        /// 
        /// </summary>
        public static readonly DependencyProperty KeyProperty = DependencyProperty.Register("Key", typeof(Key), typeof(KeyTrigger), new PropertyMetadata(Key.None));

        /// <summary>
        /// 
        /// </summary>
        public static readonly DependencyProperty ModifiersProperty = DependencyProperty.Register("Modifiers", typeof(ModifierKeys), typeof(KeyTrigger), new PropertyMetadata(ModifierKeys.None));

        /// <summary>
        /// Any modifier keys which must accompany the key press
        /// </summary>
        public ModifierKeys Modifiers
        {
            get { return (ModifierKeys)this.GetValue(KeyTrigger.ModifiersProperty); }
            set { this.SetValue(KeyTrigger.ModifiersProperty, value); }
        }

        private FrameworkElement FindRoot(FrameworkElement element)
        {
            FrameworkElement parent = element;
            while (parent != null)
            {
                element = parent;
                parent = element.Parent as FrameworkElement;
            }
            return element;
        }

        /// <summary>
        /// Attach the appropriate events.
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            this.root = this.FindRoot(this.AssociatedObject);
            this.root.KeyDown += this.HandleHostKeyDown;
        }

        /// <summary>
        /// Remove the appropriate events.
        /// </summary>
        protected override void OnDetaching()
        {
            base.OnDetaching();

            this.root.KeyDown -= this.HandleHostKeyDown;
        }

        private void HandleHostKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == this.Key && Keyboard.Modifiers == this.Modifiers)
            {
                this.InvokeActions(e);
            }
        }
    }
}
